package simplescenegraph.utils;

import java.util.Enumeration;

public final class ArrayTree<E> implements Container {

	public static final class Node<T> {

		Node<T> parent = null;
		Node<T> brother = null;
		Node<T> firstChild = null;
		T data = null;

		public T getData() {
			return data;
		}

		public int depth() {
			int i0 = 0;
			Node<T> n0 = this;
			while (n0.parent != null) {
				n0 = n0.parent;
				i0++;
			}
			return i0;
		}
	}

	private Node<E> root;
	private int elementCounter;

	public ArrayTree() {
		root = null;
		elementCounter = 0;
	}

	public Node<E> add(final Node<E> parent, E e0) {
		Node<E> n0 = new Node<E>(), n1;
		n0.parent = parent;
		n0.data = e0;

		if (parent == null) {
			root = n0;
		} else {
			n1 = parent.firstChild;
			if (n1 == null)
				parent.firstChild = n0;
			else {
				while (n1.brother != null)
					n1 = n1.brother;
				n1.brother = n0;
			}
		}
		elementCounter++;
		return n0;
	}

	public void remove(final Node<E> n0) {
		if (n0 == root) {
			root = null;
		} else {
			Node<E> n1 = n0.parent.firstChild;

			if (n1 == n0) {
				n0.parent.firstChild = null;
			} else {
				while (n1.brother != n0)
					n1 = n1.brother;

				n1.brother = null;
			}
		}
	}

	public boolean isEmpty() {
		return root == null;
	}

	public int size() {
		return elementCounter;
	}

	public Node<E> next(final Node<E> n0) {
		Node<E> pointer = n0;
		if (pointer == root) {
			pointer = root.firstChild;
		} else {
			if (pointer.firstChild != null)
				pointer = pointer.firstChild;
			else if (pointer.brother != null)
				pointer = pointer.brother;
			else if (pointer.parent != null) {
				pointer = pointer.parent.brother;
			} else
				pointer = null;
		}
		return pointer;
	}

	public Enumeration<E> getEnumeration() {
		return new Enumeration<E>() {

			Node<E> pointer = root;

			public boolean hasMoreElements() {
				return pointer != null;
			}

			public E nextElement() {
				E e0 = pointer.getData();

				pointer = next(pointer);

				return e0;
			}

		};
	}

	public Node<E> getRoot() {
		return root;
	}
	

	private static String ident(int level) {
		int i0 = 0;
		StringBuffer sb0 = new StringBuffer(level);
		while (i0++ < level)
			sb0.append('\t');
		return sb0.toString();
	}	
	
	public String toString() {
		/*
		 * Enumeration<Routine> e0 = routinesTree.getEnumeration(); while
		 * (e0.hasMoreElements()) { Routine r0 = e0.nextElement();
		 * System.out.println("- " + r0.name + ": " + (r0.endTime -
		 * r0.beginTime) + " ms"); }
		 */
		Node<E> n0 = root;
		StringBuffer sb0 = new StringBuffer();
		do
			sb0.append(ident(n0.depth()) + n0.getData().toString() + '\n');
		while ((n0 = next(n0)) != null);
		
		return sb0.toString();
	}

}
